package com.cfk.bookmarkdirectory.window;


import com.cfk.bookmarkdirectory.config.BookmarkDirectoryState;
import com.cfk.bookmarkdirectory.util.BookmarkDirectoryUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.ui.treeStructure.Tree;
import org.jetbrains.annotations.NotNull;
import com.cfk.bookmarkdirectory.model.BookmarkNode;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDialog;
import com.intellij.openapi.fileChooser.FileChooserFactory;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;


import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * author 3156056300@qq.com
 */
class BookmarkDirectoryWindow {
    private final Project project;
    private final JPanel mainPanel;
    private final Tree bookmarkTree;
    private final DefaultTreeModel treeModel;
    private  BookmarkDirectoryState state;

    public BookmarkDirectoryWindow(Project project) {
        this.project = project;
        this.mainPanel = new JPanel(new BorderLayout());
        
        // 初始化state并加载书签
        this.state = BookmarkDirectoryState.getInstance(project);

        // 创建树的根节点
        DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
        this.treeModel = new DefaultTreeModel(root);
        this.bookmarkTree = new Tree(treeModel);

        // 设置树的基本属性
        bookmarkTree.setRootVisible(true);
        bookmarkTree.setShowsRootHandles(true);
        bookmarkTree.setEditable(true);

        // 加载已保存的书签
        loadSavedBookmarks();

        // 订阅项目打开事件以处理后续的项目重新打开
        project.getMessageBus().connect().subscribe(ProjectManager.TOPIC, new ProjectManagerListener() {
            @Override
            public void projectOpened(@NotNull Project openedProject) {
                if (project.equals(openedProject)) {
                    loadSavedBookmarks();
                }
            }
        });

        // 添加滚动面板
        JScrollPane scrollPane = new JScrollPane(bookmarkTree);
        mainPanel.add(scrollPane, BorderLayout.CENTER);

        // 创建工具栏
        JPanel toolbar = new JPanel(new FlowLayout(FlowLayout.LEFT));
        JButton addButton = new JButton("add");
        JButton addFolderButton = new JButton("add group");
        JButton removeButton = new JButton("delete");
        JButton editButton = new JButton("edit");
        JButton exportButton = new JButton("export");
        JButton importButton = new JButton("import");

        toolbar.add(addButton);
        toolbar.add(addFolderButton);
        toolbar.add(removeButton);
        toolbar.add(editButton);
        toolbar.add(exportButton);
        toolbar.add(importButton);
        mainPanel.add(toolbar, BorderLayout.NORTH);

        // 添加按钮事件监听器
        addButton.addActionListener(e -> addBookmark());
        addFolderButton.addActionListener(e -> addFolder());
        removeButton.addActionListener(e -> removeNode());
        editButton.addActionListener(e -> editNodeName());
        exportButton.addActionListener(e -> exportBookmarks());
        importButton.addActionListener(e -> importBookmarks());

        // 添加树节点选择事件监听器
        bookmarkTree.addTreeSelectionListener(e -> {
            DefaultMutableTreeNode node = (DefaultMutableTreeNode)
                    bookmarkTree.getLastSelectedPathComponent();

            if (node != null && node instanceof BookmarkNode) {
                ((BookmarkNode) node).navigateToDirectory(project);
            }
        });
    }

    private void loadSavedBookmarks() {
        if (state == null) {
            return;
        }
        List<BookmarkDirectoryState.BookmarkNodeState> savedBookmarks = state.loadBookmarks();
        if (savedBookmarks == null) {
            return;
        }
        DefaultMutableTreeNode root = (DefaultMutableTreeNode) treeModel.getRoot();

        for (BookmarkDirectoryState.BookmarkNodeState bookmarkState : savedBookmarks) {
            if (bookmarkState != null) {
                BookmarkNode node = BookmarkDirectoryUtil.convertToNode(bookmarkState);
                if (node != null) {
                    treeModel.insertNodeInto(node, root, root.getChildCount());
                    expandAllNodes(new TreePath(node.getPath()));
                }
            }
        }
    }

    private void expandAllNodes(TreePath path) {
        if (path != null) {
            bookmarkTree.expandPath(path);
            DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
            for (int i = 0; i < node.getChildCount(); i++) {
                TreePath childPath = path.pathByAddingChild(node.getChildAt(i));
                expandAllNodes(childPath);
            }
        }
    }

    private void saveCurrentBookmarks() {
        if (state == null) {
            state = BookmarkDirectoryState.getInstance(project);
            if (state == null) {
                Messages.showErrorDialog(project, "Unable to save bookmarks: state object initialization failed", "Error");
                return;
            }
        }
        DefaultMutableTreeNode root = (DefaultMutableTreeNode) treeModel.getRoot();
        List<BookmarkDirectoryState.BookmarkNodeState> bookmarkStates = new ArrayList<>();
        for (int i = 0; i < root.getChildCount(); i++) {
            DefaultMutableTreeNode child = (DefaultMutableTreeNode) root.getChildAt(i);
            if (child instanceof BookmarkNode) {
                BookmarkNode bookmarkNode = (BookmarkNode) child;
                bookmarkStates.add(convertToNodeState(bookmarkNode));
            }
        }
        state.saveBookmarks(bookmarkStates);
    }

    private BookmarkDirectoryState.BookmarkNodeState convertToNodeState(BookmarkNode node) {
        BookmarkDirectoryState.BookmarkNodeState nodeState = new BookmarkDirectoryState.BookmarkNodeState();
        nodeState.name = node.getName();
        nodeState.directoryPath = node.getDirectoryPath();
        nodeState.isDirectory = node.isDirectory();

        // 递归处理子节点
        for (int i = 0; i < node.getChildCount(); i++) {
            Object child = node.getChildAt(i);
            if (child instanceof BookmarkNode) {
                nodeState.children.add(convertToNodeState((BookmarkNode) child));
            }
        }

        return nodeState;
    }

    private void exportBookmarks() {
        if (state == null) {
            Messages.showErrorDialog(project, "Unable to export bookmarks: state object is null", "Error");
            return;
        }

        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("Export Bookmark Configuration");
        fileChooser.setFileFilter(new javax.swing.filechooser.FileNameExtensionFilter("JSON files", "json"));

        if (fileChooser.showSaveDialog(mainPanel) == JFileChooser.APPROVE_OPTION) {
            File file = fileChooser.getSelectedFile();
            if (!file.getName().toLowerCase().endsWith(".json")) {
                file = new File(file.getParentFile(), file.getName() + ".json");
            }
            try {
                BookmarkDirectoryUtil.exportToJson(state.loadBookmarks(), file);
                Messages.showInfoMessage(project, "Bookmark configuration has been successfully exported to: " + file.getPath(), "Export Successful");
            } catch (IOException ex) {
                Messages.showErrorDialog(project, "Export failed: " + ex.getMessage(), "Error");
            }
        }
    }

    private void importBookmarks() {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("Import Bookmark Configuration");
        fileChooser.setFileFilter(new javax.swing.filechooser.FileNameExtensionFilter("JSON files", "json"));

        if (fileChooser.showOpenDialog(mainPanel) == JFileChooser.APPROVE_OPTION) {
            try {
                List<BookmarkDirectoryState.BookmarkNodeState> bookmarks = BookmarkDirectoryUtil.importFromJson(fileChooser.getSelectedFile());
                DefaultMutableTreeNode root = (DefaultMutableTreeNode) treeModel.getRoot();
                root.removeAllChildren();
                treeModel.reload();

                for (BookmarkDirectoryState.BookmarkNodeState bookmark : bookmarks) {
                    BookmarkNode node = BookmarkDirectoryUtil.convertToNode(bookmark);
                    treeModel.insertNodeInto(node, root, root.getChildCount());
                    expandAllNodes(new TreePath(node.getPath()));
                }

                state.loadState(new BookmarkDirectoryState.State());
                saveCurrentBookmarks();
                Messages.showInfoMessage(project, "Bookmark configuration has been successfully imported", "Import Successful");
            } catch (IOException ex) {
                Messages.showErrorDialog(project, "Import failed: " + ex.getMessage(), "Error");
            }
        }
    }

    private void addBookmark() {
        FileChooserDescriptor descriptor = new FileChooserDescriptor(false, true, false, false, false, false);
        descriptor.setTitle("Select Directory");
        FileChooserDialog chooser = FileChooserFactory.getInstance().createFileChooser(descriptor, project, null);
        
        var files = chooser.choose(project);
        if (files.length > 0) {
            var selectedDir = files[0];
            String dirPath = selectedDir.getPath();
            String dirName = selectedDir.getName();
            
            BookmarkNode newNode = new BookmarkNode(dirName, dirPath, true);
            DefaultMutableTreeNode parent = (DefaultMutableTreeNode) bookmarkTree.getLastSelectedPathComponent();
            if (parent == null) {
                parent = (DefaultMutableTreeNode) treeModel.getRoot();
            }
            treeModel.insertNodeInto(newNode, parent, parent.getChildCount());
            TreePath path = new TreePath(parent.getPath());
            bookmarkTree.expandPath(path);
            saveCurrentBookmarks();
        }
    }

    private void addFolder() {
        String folderName = Messages.showInputDialog(project, "Please enter directory name:", "Add Directory", Messages.getQuestionIcon());
        if (folderName != null && !folderName.trim().isEmpty()) {
            BookmarkNode newNode = new BookmarkNode(folderName, "", false);
            DefaultMutableTreeNode parent = (DefaultMutableTreeNode) bookmarkTree.getLastSelectedPathComponent();
            if (parent == null) {
                parent = (DefaultMutableTreeNode) treeModel.getRoot();
            }
            treeModel.insertNodeInto(newNode, parent, parent.getChildCount());
            TreePath path = new TreePath(parent.getPath());
            bookmarkTree.expandPath(path);
            saveCurrentBookmarks();
        }
    }

    private void removeNode() {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) bookmarkTree.getLastSelectedPathComponent();
        if (node != null && node != treeModel.getRoot()) {
            treeModel.removeNodeFromParent(node);
            saveCurrentBookmarks();
        }
    }

    private void editNodeName() {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) bookmarkTree.getLastSelectedPathComponent();
        if (node != null && node != treeModel.getRoot()) {
            String newName = Messages.showInputDialog(project, "Please enter new name:", "Edit Name", Messages.getQuestionIcon(), node.toString(), null);
            if (newName != null && !newName.trim().isEmpty()) {
                if (node instanceof BookmarkNode) {
                    ((BookmarkNode) node).setName(newName);
                    treeModel.nodeChanged(node);
                    saveCurrentBookmarks();
                }
            }
        }
    }

    public JPanel getContent() {
        return mainPanel;
    }
}